package com.etc.controller;

import com.etc.entity.Chat;
import com.etc.entity.GiftRecord;
import com.etc.entity.Room;
import com.etc.entity.User;
import com.etc.service.LiveService;
import com.etc.service.impl.LiveServiceImpl;
import com.google.gson.Gson;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.socket.*;

import javax.websocket.EncodeException;
import javax.websocket.Session;
import java.io.IOException;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;


public class ChatHandler implements WebSocketHandler {

    //静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。
    private static int onlineCount = 0;

    private static final Map<String, Set<WebSocketSession>> rooms = new ConcurrentHashMap();

    @Autowired
    private LiveService liveService;
    
    /**
     * 日志对象
     */
    Logger logger = Logger.getLogger(ChatHandler.class);



    /**
     * 建立websocket连接时调用该方法
     * @param webSocketSession
     * @throws Exception
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession webSocketSession) throws Exception {
        String roomName = getRoomName(webSocketSession);
        // 将session按照房间名来存储，将各个房间的用户隔离
        if (!rooms.containsKey(roomName)) {
            // 创建房间不存在时，创建房间
            Set<WebSocketSession> room = new HashSet<>();
            // 添加用户
            room.add(webSocketSession);
            rooms.put(roomName, room);
            addOnlineCount();
            logger.debug("DEBUG测试:有新连接加入！"+webSocketSession);
            logger.debug("DEBUG测试:有新连接加入！当前在线人数为" + getOnlineCount());
        } else {
            // 房间已存在，直接添加用户到相应的房间
            addOnlineCount();
            logger.debug("DEBUG测试:有新连接加入！当前在线人数为" + getOnlineCount());
            rooms.get(roomName).add(webSocketSession);
        }
        User user = new User();
        user.setUserName("系统提示");
        Room room = liveService.queryRoomById(roomName);
        Chat chat = new Chat("",user,"欢迎来到"+room.getUserId().getUserName()+"的直播间，喜欢就点关注吧。斗鱼依法对直播内容进行24小时巡查，禁止传播违法违规、封建迷信、暴力血腥、低俗色情、招嫖诈骗违禁品等不良信息，坚决维护青少年群体精神文明健康。请勿轻信各类招聘征婚、代练代抽、刷钻、购买礼包码、游戏币等广告信息。且如主播在推广商品中诱导私下交易，请谨慎判断，以免上当受骗。","");
        Gson gson = new Gson();
        String chatString = gson.toJson(chat);
        try {
            TextMessage message = new TextMessage(chatString);
            webSocketSession.sendMessage(message);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 客户端调用websocket.send时候，会调用该方法,进行数据通信
     * @param webSocketSession
     * @param webSocketMessage
     * @throws Exception
     */
    @Override
    public void handleMessage(WebSocketSession webSocketSession, WebSocketMessage<?> webSocketMessage) throws Exception {
        String roomName = getRoomName(webSocketSession);
        logger.debug("DEBUG测试:来自客户端的消息:" + webSocketMessage.toString());
        Gson gson =new Gson();
        if ("Chat".equals(getChannel(webSocketSession))){
            Chat chat = gson.fromJson(webSocketMessage.getPayload().toString(), Chat.class);
            logger.debug("DEBUG测试:"+chat);
            boolean b =liveService.addChat(chat);
            if (b){
                String chatString = gson.toJson(chat);
                //群发消息
                for (WebSocketSession session : rooms.get(roomName)) {
                    try {
                        TextMessage message = new TextMessage(chatString);
                        session.sendMessage(message);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }else{
                logger.debug("DEBUG测试:发生错误");
            }
        }else if ("GiftRecord".equals(getChannel(webSocketSession))){
            GiftRecord giftRecord = gson.fromJson(webSocketMessage.getPayload().toString(), GiftRecord.class);
            String giftRecordString = gson.toJson(giftRecord);
            //群发消息
            for (WebSocketSession session : rooms.get(roomName)) {
                try {
                    TextMessage message = new TextMessage(giftRecordString);
                    session.sendMessage(message);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    /**
     * 传输过程出现异常时，调用该方法
     * @param webSocketSession
     * @param throwable
     * @throws Exception
     */
    @Override
    public void handleTransportError(WebSocketSession webSocketSession, Throwable throwable) throws Exception {
        logger.debug("DEBUG测试:发生错误");
        throwable.printStackTrace();
    }

    /**
     * 关闭websocket时调用该方法
     * @param webSocketSession
     * @param closeStatus
     * @throws Exception
     */
    @Override
    public void afterConnectionClosed(WebSocketSession webSocketSession, CloseStatus closeStatus) throws Exception {
        String roomName = getRoomName(webSocketSession);
        rooms.get(roomName).remove(webSocketSession);
        subOnlineCount(); //在线数减
        logger.debug("DEBUG测试:有一连接关闭！当前在线人数为" + getOnlineCount());
    }

    
    @Override
    public boolean supportsPartialMessages() {
        logger.debug("DEBUG测试:supportsPartialMessages");
        return false;
    }

    

    /**
     * getRoomName:获取房间Id
     *
     * @author liuchao
     * @param session
     * @return
     * @since JDK 1.7
     */
    private String getRoomName(WebSocketSession session) {
        try {
            String roomName = (String) session.getAttributes().get("roomName");
            return roomName;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * getChannel:获取频道
     *
     * @author liuchao
     * @param session
     * @return
     * @since JDK 1.7
     */
    private String getChannel(WebSocketSession session) {
        try {
            String channel = (String) session.getAttributes().get("channel");
            return channel;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    public static synchronized int getOnlineCount() {
        return onlineCount;
    }
    public static synchronized void addOnlineCount() {
        ChatHandler.onlineCount++;
    }
    public static synchronized void subOnlineCount() {
        ChatHandler.onlineCount--;
    }
}
